/**
 * Trabajo de Ingeniería de Software 2
 * Año 2008
 * Sistema de Reserva de Recursos.
 * Desarrolladores: - Marcelo Ferreira.
 *                  - Christian Gómez.
 *                  - Marcelo Rodas.
 */
package controller;

import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import javax.faces.application.FacesMessage;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.faces.FacesException;
import java.util.HashMap;
//import javax.faces.validator.ValidatorException;
import javax.transaction.UserTransaction;
import modelo.Cancelacion;
import modelo.Recurso;
import modelo.Reserva;
import modelo.Solicitudreserva;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import modelo.Tiporecurso;
import modelo.Usoretiro;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Vector;
import javax.servlet.http.HttpSession;
import modelo.Usuario;


/**
 * Controlador de las Funcionalidades de una Reserva.
 * Utilizado para manejar la capa de controlador (MVC)
 * del sistema.
 * @author mrodas
 * @version 1.0
 */
public class ReservaController implements ReservaControllerInterface {

    // POJO de Reserva Representada.
    private Reserva reserva = null;
    // Lista de Reservas.
    private List<Reserva> reservas = null;
    // Formatos para el día y hora
    DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    DateFormat horaFormat = new SimpleDateFormat("HH:mm");
    // Transacción del usuario.
    @Resource
    private UserTransaction utx = null;
    // Administrador de la Persistencia de la Reserva.
    // Relaciona al Controlador con el Modelo (MVC)
    @PersistenceUnit(unitName = "sistemaReservaPU")
    private EntityManagerFactory emf = null;

    /**
     * Getter del Administrador de Entidades.
     * @return EntityManager
     */
    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }
    
/*    // ---------- Variables para paginar en el jsp -------------
    // variable auxiliar que indica el tamaño de conjunto
    public int batchSize = 100;
    // variable auxiliar para indicar el 1er elemento
    private int firstItem = 0;*/
    // variable auxiliar utilizado como contador de elementos
    private int itemCount = -1;
    // ---------------------------------------------------------
    
    public ReservaController(Reserva r){
        this.reserva = r;
    }
    
    /**
     * Constructor Básico de la Clase
     */
    public ReservaController(){
        FacesContext context = FacesContext.getCurrentInstance();
        context.getExternalContext().getSessionMap().put("reserva_list", this);
    }

    /**
     * Setter del Uso-Retiro de la Reserva Representada.
     * @param usoretiroCollection
     */
    public void setUsoretiroCollectionOfReserva(Usoretiro[] usoretiroCollection) {
        List<Usoretiro> usoretiroCollectionList = Arrays.asList(usoretiroCollection);
        reserva.setUsoretiroCollection(usoretiroCollectionList);
    }

    /**
     * Getter del Uso-Retiro de la Reserva Representada.
     * @return Usoretiro[]
     */
    public Usoretiro[] getUsoretiroCollectionOfReserva() {
        Collection<Usoretiro> usoretiroCollection = reserva.getUsoretiroCollection();
        if (usoretiroCollection == null) {
            return new Usoretiro[0];
        }
        return usoretiroCollection.toArray(new Usoretiro[0]);
    }

    /**
     * Setter de la Cancelacion de la Reserva Representada.
     * @param cancelacionCollection
     */
    public void setCancelacionCollectionOfReserva(Cancelacion[] cancelacionCollection) {
        List<Cancelacion> cancelacionCollectionList = Arrays.asList(cancelacionCollection);
        reserva.setCancelacionCollection(cancelacionCollectionList);
    }

    /**
     * Getter de la Cancelacion de la Reserva Representada.
     * @return Cancelacion[]
     */
    public Cancelacion[] getCancelacionCollectionOfReserva() {
        Collection<Cancelacion> cancelacionCollection = reserva.getCancelacionCollection();
        if (cancelacionCollection == null) {
            return new Cancelacion[0];
        }
        return cancelacionCollection.toArray(new Cancelacion[0]);
    }

    /**
     * Obtiene las Reservas Disponibles (de reservas).
     * @return getReservasAvailable(false)
     */
    public SelectItem[] getReservasAvailableSelectMany() {
        return getReservasAvailable(false);
    }

    /**
     * Obtiene la Reserva Disponible (de reservas).
     * @return getReservasAvailable(true)
     */
    public SelectItem[] getReservasAvailableSelectOne() {
        return getReservasAvailable(true);
    }

    /*
     * Calculo de Reservas disponibles
     *   "one" true indica que se debe ingresar una nueva reserva
     *   al inicio de las reservas disponibles.
     */
    private SelectItem[] getReservasAvailable(boolean one) {
        List<Reserva> allReservas = getReservas(true);
        int size = one ? allReservas.size() + 1 : allReservas.size();
        SelectItem[] items = new SelectItem[size];
        int i = 0;
        if (one) {
            items[0] = new SelectItem("", "---");
            i++;
        }
        for (Reserva x : allReservas) {
            items[i++] = new SelectItem(x, x.toString());
        }
        return items;
    }

    /**
     * Getter de la Reserva Representada.
     * @return Reserva
     */
    public Reserva getReserva() {
        if (reserva == null) {
            reserva = getReservaFromRequest();
        }
        if (reserva == null) {
            reserva = new Reserva();
        }
        return reserva;
    }

    /**
     * Función de Navegación a la Pagina List.jsp
     * @return String
     */
    public String listSetup() {
        reset(true);
        reservas=this.getReservas(false);
        return "reserva_list";
    }

    /**
     * Setter de la lista de Reserva atributo.
     * @param lista
     */
    public void setReservas(List<Reserva> lista){
        this.reservas = lista;
    }
    
    /**
     * Función para obtener los recursos relacionados al tipo de recurso
     * correspondiente a la reserva representada.
     * @return SelectItem[]
     */
    public SelectItem[] getRecursosAvailableSelectMany() {
        boolean one =false;
        List<Recurso> allRecursos = getRecursos();
        int size = one ? allRecursos.size() + 1 : allRecursos.size();
        SelectItem[] items = new SelectItem[size];
        int i = 0;
        if (one) {
            items[0] = new SelectItem("", "---");
            i++;
        }
        for (Recurso x : allRecursos) {
            items[i++] = new SelectItem(x, x.toString());
        }
        return items;
    }
    
    /**
     * Getter del atributo Recursos.
     * @return List<Recurso>
     */
    public List<Recurso> getRecursos() {
        EntityManager em = getEntityManager();
        Tiporecurso TipoRecurso = this.getReserva().getIdRecurso().getIdTipoRecurso();
        
        try {
            Query q = em.createQuery("select object(o) from Recurso as o where o.disponible=1 and o.idTipoRecurso.idTipoRecurso="+TipoRecurso.getIdTipoRecurso());
            return q.getResultList();
        } finally {
            em.close();
        }
    }
    
    
    /**
     * Función de Navegación a la Pagina New.jsp
     * @return String
     */
    public String createSetup() {
        reset(false);
        reserva = new Reserva();
        return "reserva_create";
    }

    /**
     * Función que Almacena (crea) la Reserva Representada.
     * (Guardar Reserva). 
     * @return String
     */
    public String create() {
        if (reserva.getUsoretiroCollection() == null) {
            reserva.setUsoretiroCollection(new ArrayList<Usoretiro>());
        }
        if (reserva.getCancelacionCollection() == null) {
            reserva.setCancelacionCollection(new ArrayList<Cancelacion>());
        }
        EntityManager em = getEntityManager();
        try {
            utx.begin();
            Recurso idRecurso = reserva.getIdRecurso();
            if (idRecurso != null) {
                idRecurso = em.getReference(idRecurso.getClass(), idRecurso.getIdRecurso());
                reserva.setIdRecurso(idRecurso);
            }
            Solicitudreserva idSolicitudReserva = reserva.getIdSolicitudReserva();
            if (idSolicitudReserva != null) {
                idSolicitudReserva = em.getReference(idSolicitudReserva.getClass(), idSolicitudReserva.getIdSolicitudReserva());
                reserva.setIdSolicitudReserva(idSolicitudReserva);
            }
            List<Usoretiro> attachedUsoretiroCollection = new ArrayList<Usoretiro>();
            for (Usoretiro usoretiroCollectionUsoretiroToAttach : reserva.getUsoretiroCollection()) {
                usoretiroCollectionUsoretiroToAttach = em.getReference(usoretiroCollectionUsoretiroToAttach.getClass(), usoretiroCollectionUsoretiroToAttach.getIdUsoRetiro());
                attachedUsoretiroCollection.add(usoretiroCollectionUsoretiroToAttach);
            }
            reserva.setUsoretiroCollection(attachedUsoretiroCollection);
            List<Cancelacion> attachedCancelacionCollection = new ArrayList<Cancelacion>();
            for (Cancelacion cancelacionCollectionCancelacionToAttach : reserva.getCancelacionCollection()) {
                cancelacionCollectionCancelacionToAttach = em.getReference(cancelacionCollectionCancelacionToAttach.getClass(), cancelacionCollectionCancelacionToAttach.getIdCancelacion());
                attachedCancelacionCollection.add(cancelacionCollectionCancelacionToAttach);
            }
            reserva.setCancelacionCollection(attachedCancelacionCollection);
            em.persist(reserva);
            if (idRecurso != null) {
                idRecurso.getReservaCollection().add(reserva);
                idRecurso = em.merge(idRecurso);
            }
            if (idSolicitudReserva != null) {
                idSolicitudReserva.getReservaCollection().add(reserva);
                idSolicitudReserva = em.merge(idSolicitudReserva);
            }
            for (Usoretiro usoretiroCollectionUsoretiro : reserva.getUsoretiroCollection()) {
                Reserva oldIdReservaOfUsoretiroCollectionUsoretiro = usoretiroCollectionUsoretiro.getIdReserva();
                usoretiroCollectionUsoretiro.setIdReserva(reserva);
                usoretiroCollectionUsoretiro = em.merge(usoretiroCollectionUsoretiro);
                if (oldIdReservaOfUsoretiroCollectionUsoretiro != null) {
                    oldIdReservaOfUsoretiroCollectionUsoretiro.getUsoretiroCollection().remove(usoretiroCollectionUsoretiro);
                    oldIdReservaOfUsoretiroCollectionUsoretiro = em.merge(oldIdReservaOfUsoretiroCollectionUsoretiro);
                }
            }
            for (Cancelacion cancelacionCollectionCancelacion : reserva.getCancelacionCollection()) {
                Reserva oldIdReservaOfCancelacionCollectionCancelacion = cancelacionCollectionCancelacion.getIdReserva();
                cancelacionCollectionCancelacion.setIdReserva(reserva);
                cancelacionCollectionCancelacion = em.merge(cancelacionCollectionCancelacion);
                if (oldIdReservaOfCancelacionCollectionCancelacion != null) {
                    oldIdReservaOfCancelacionCollectionCancelacion.getCancelacionCollection().remove(cancelacionCollectionCancelacion);
                    oldIdReservaOfCancelacionCollectionCancelacion = em.merge(oldIdReservaOfCancelacionCollectionCancelacion);
                }
            }
            utx.commit();
            addSuccessMessage("La Reserva fue creada exitosamente.");
        } catch (Exception ex) {
            try {
                if (findReserva(reserva.getIdReserva()) != null) {
                    addErrorMessage("La Reserva " + reserva + " ya existe.");
                } else {
                    ensureAddErrorMessage(ex, "Ocurrió un error de persistencia.");
                }
                utx.rollback();
            } catch (Exception e) {
                ensureAddErrorMessage(e, "Ocurrio un error al realizar rollback de la transacción.");
            }
            return null;
        } finally {
            em.close();
        }
        return listSetup();
    }

    /**
     * Función de Navegación a la Pagina Detail.jsp
     * @return String
     */
    public String detailSetup() {
        return scalarSetup("reserva_detail");
    }

    /**
     * Función de Navegación a la Pagina Edit.jsp
     * @return String
     */
    public String editSetup() {
        return scalarSetup("reserva_edit");
    }

    /*
     * Función de Navegación General, controla si existe la ruta de
     * navegación.
     */
    private String scalarSetup(String destination) {
        reset(false);
        reserva = getReservaFromRequest();
        if (reserva == null) {
            String requestReservaString = getRequestParameter("jsfcrud.currentReserva");
            addErrorMessage("La reserva con id " + requestReservaString + " no existe.");
            String relatedControllerOutcome = relatedControllerOutcome();
            if (relatedControllerOutcome != null) {
                return relatedControllerOutcome;
            }
            return listSetup();
        }
        return destination;
    }

    /**
     * Función que almacena los cambios realizados sobre la
     * Reserva Representada. Esta relacionada a la reasignación
     * Recursos en la reserva.
     * (Reasignar Recurso en la Reserva)
     * @return String
     */
    public String edit() {
        ReservaConverter converter = new ReservaConverter();
        String reservaString = converter.getAsString(FacesContext.getCurrentInstance(), null, reserva);
        String currentReservaString = getRequestParameter("jsfcrud.currentReserva");
        if (reservaString == null || reservaString.length() == 0 || !reservaString.equals(currentReservaString)) {
            String outcome = editSetup();
            if ("reserva_edit".equals(outcome)) {
                addErrorMessage("No se pudo editar la reserva. Pruebe De nuevo.");
            }
            return outcome;
        }
        if (this.verificarSolapamiento().length()>0){
            addErrorMessage(this.verificarSolapamiento());
            return "";
        }

        EntityManager em = getEntityManager();
        try {
            utx.begin();
            Reserva persistentReserva = em.find(Reserva.class, reserva.getIdReserva());
            Recurso idRecursoOld = persistentReserva.getIdRecurso();
            Recurso idRecursoNew = reserva.getIdRecurso();
            Solicitudreserva idSolicitudReservaOld = persistentReserva.getIdSolicitudReserva();
            Solicitudreserva idSolicitudReservaNew = reserva.getIdSolicitudReserva();
            Collection<Usoretiro> usoretiroCollectionOld = persistentReserva.getUsoretiroCollection();
            Collection<Usoretiro> usoretiroCollectionNew = reserva.getUsoretiroCollection();
            Collection<Cancelacion> cancelacionCollectionOld = persistentReserva.getCancelacionCollection();
            Collection<Cancelacion> cancelacionCollectionNew = reserva.getCancelacionCollection();
            if (idRecursoNew != null) {
                idRecursoNew = em.getReference(idRecursoNew.getClass(), idRecursoNew.getIdRecurso());
                reserva.setIdRecurso(idRecursoNew);
            }
            if (idSolicitudReservaNew != null) {
                idSolicitudReservaNew = em.getReference(idSolicitudReservaNew.getClass(), idSolicitudReservaNew.getIdSolicitudReserva());
                reserva.setIdSolicitudReserva(idSolicitudReservaNew);
            }
            List<Usoretiro> attachedUsoretiroCollectionNew = new ArrayList<Usoretiro>();
            for (Usoretiro usoretiroCollectionNewUsoretiroToAttach : usoretiroCollectionNew) {
                usoretiroCollectionNewUsoretiroToAttach = em.getReference(usoretiroCollectionNewUsoretiroToAttach.getClass(), usoretiroCollectionNewUsoretiroToAttach.getIdUsoRetiro());
                attachedUsoretiroCollectionNew.add(usoretiroCollectionNewUsoretiroToAttach);
            }
            usoretiroCollectionNew = attachedUsoretiroCollectionNew;
            reserva.setUsoretiroCollection(usoretiroCollectionNew);
            List<Cancelacion> attachedCancelacionCollectionNew = new ArrayList<Cancelacion>();
            for (Cancelacion cancelacionCollectionNewCancelacionToAttach : cancelacionCollectionNew) {
                cancelacionCollectionNewCancelacionToAttach = em.getReference(cancelacionCollectionNewCancelacionToAttach.getClass(), cancelacionCollectionNewCancelacionToAttach.getIdCancelacion());
                attachedCancelacionCollectionNew.add(cancelacionCollectionNewCancelacionToAttach);
            }
            cancelacionCollectionNew = attachedCancelacionCollectionNew;
            reserva.setCancelacionCollection(cancelacionCollectionNew);
            reserva = em.merge(reserva);
            if (idRecursoOld != null && !idRecursoOld.equals(idRecursoNew)) {
                idRecursoOld.getReservaCollection().remove(reserva);
                idRecursoOld = em.merge(idRecursoOld);
            }
            if (idRecursoNew != null && !idRecursoNew.equals(idRecursoOld)) {
                idRecursoNew.getReservaCollection().add(reserva);
                idRecursoNew = em.merge(idRecursoNew);
            }
            if (idSolicitudReservaOld != null && !idSolicitudReservaOld.equals(idSolicitudReservaNew)) {
                idSolicitudReservaOld.getReservaCollection().remove(reserva);
                idSolicitudReservaOld = em.merge(idSolicitudReservaOld);
            }
            if (idSolicitudReservaNew != null && !idSolicitudReservaNew.equals(idSolicitudReservaOld)) {
                idSolicitudReservaNew.getReservaCollection().add(reserva);
                idSolicitudReservaNew = em.merge(idSolicitudReservaNew);
            }
            for (Usoretiro usoretiroCollectionOldUsoretiro : usoretiroCollectionOld) {
                if (!usoretiroCollectionNew.contains(usoretiroCollectionOldUsoretiro)) {
                    usoretiroCollectionOldUsoretiro.setIdReserva(null);
                    usoretiroCollectionOldUsoretiro = em.merge(usoretiroCollectionOldUsoretiro);
                }
            }
            for (Usoretiro usoretiroCollectionNewUsoretiro : usoretiroCollectionNew) {
                if (!usoretiroCollectionOld.contains(usoretiroCollectionNewUsoretiro)) {
                    Reserva oldIdReservaOfUsoretiroCollectionNewUsoretiro = usoretiroCollectionNewUsoretiro.getIdReserva();
                    usoretiroCollectionNewUsoretiro.setIdReserva(reserva);
                    usoretiroCollectionNewUsoretiro = em.merge(usoretiroCollectionNewUsoretiro);
                    if (oldIdReservaOfUsoretiroCollectionNewUsoretiro != null && !oldIdReservaOfUsoretiroCollectionNewUsoretiro.equals(reserva)) {
                        oldIdReservaOfUsoretiroCollectionNewUsoretiro.getUsoretiroCollection().remove(usoretiroCollectionNewUsoretiro);
                        oldIdReservaOfUsoretiroCollectionNewUsoretiro = em.merge(oldIdReservaOfUsoretiroCollectionNewUsoretiro);
                    }
                }
            }
            for (Cancelacion cancelacionCollectionOldCancelacion : cancelacionCollectionOld) {
                if (!cancelacionCollectionNew.contains(cancelacionCollectionOldCancelacion)) {
                    cancelacionCollectionOldCancelacion.setIdReserva(null);
                    cancelacionCollectionOldCancelacion = em.merge(cancelacionCollectionOldCancelacion);
                }
            }
            for (Cancelacion cancelacionCollectionNewCancelacion : cancelacionCollectionNew) {
                if (!cancelacionCollectionOld.contains(cancelacionCollectionNewCancelacion)) {
                    Reserva oldIdReservaOfCancelacionCollectionNewCancelacion = cancelacionCollectionNewCancelacion.getIdReserva();
                    cancelacionCollectionNewCancelacion.setIdReserva(reserva);
                    cancelacionCollectionNewCancelacion = em.merge(cancelacionCollectionNewCancelacion);
                    if (oldIdReservaOfCancelacionCollectionNewCancelacion != null && !oldIdReservaOfCancelacionCollectionNewCancelacion.equals(reserva)) {
                        oldIdReservaOfCancelacionCollectionNewCancelacion.getCancelacionCollection().remove(cancelacionCollectionNewCancelacion);
                        oldIdReservaOfCancelacionCollectionNewCancelacion = em.merge(oldIdReservaOfCancelacionCollectionNewCancelacion);
                    }
                }
            }
                //Recupera los atributos de la sesion
            HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
            //Para la audioria, que dispara el trigger de auditoria
            Usuario usuarioLogeado = (Usuario) session.getAttribute("user");
            reserva.setUserAudita(usuarioLogeado.getIdUsuario());

            utx.commit();
            addSuccessMessage("La Reserva se actualizó Correctamente.");
        } catch (Exception ex) {
            try {
                String msg = ex.getLocalizedMessage();
                if (msg != null && msg.length() > 0) {
                    addErrorMessage(msg);
                } else if (getReservaFromRequest() == null) {
                    addErrorMessage("La reserva con id " + currentReservaString + " no existe.");
                    utx.rollback();
                    return listSetup();
                } else {
                    addErrorMessage("Un error de Persistencia ocurrrio.");
                }
                utx.rollback();
            } catch (Exception e) {
                ensureAddErrorMessage(e, "Un error ocurrio al tratar de realizar rollback.");
            }
            return null;
        } finally {
            em.close();
        }
        return listSetup();
    }
    
    /*
     * Función para obtener la Reserva del Request.
     */
    private Reserva getReservaFromRequest() {
        String theId = getRequestParameter("jsfcrud.currentReserva");
        return (Reserva) new ReservaConverter().getAsObject(FacesContext.getCurrentInstance(), null, theId);
    }
    
    /*
     * Función para obtener un valor del request.
     */
    private String getRequestParameter(String key) {
        return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(key);
    }

    /**
     * Getter de Reservas (atributo local).
     * @return List<Reserva>
     */
    public List<Reserva> getReservas() {
        //if (reservas == null) {
            reservas = getReservas(false);
        //}
        return reservas;
    }

    /**
     * Getter de todas las Reservas (de la Base de Datos)
     * @param all
     * @return List<Reserva>
     */
    public List<Reserva> getReservas(boolean all) {
        EntityManager em = getEntityManager();
        try {
            
            Query q;
            q = em.createQuery("select object(o) from Reserva as o where o.idestadoreserva=1" );
           /* if (!all) {
                q.setMaxResults(batchSize);
                q.setFirstResult(getFirstItem());
            }*/
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    /*
     *-------------------------------------------------------------------
     * Funciones de manejo de Mensajes y Errores.
     *-------------------------------------------------------------------
     */
    // Asegura que se almacenen los errores
    private void ensureAddErrorMessage(Exception ex, String defaultMsg) {
        String msg = ex.getLocalizedMessage();
        if (msg != null && msg.length() > 0) {
            addErrorMessage(msg);
        } else {
            addErrorMessage(defaultMsg);
        }
    }

    /**
     * Agrega mensajes de Error para la Página.
     * @param msg
     */ 
    public static void addErrorMessage(String msg) {
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
        FacesContext.getCurrentInstance().addMessage(null, facesMsg);
    }

    /**
     * Agrega mensajes de Exito para la Página.
     * @param msg
     */ 
    public static void addSuccessMessage(String msg) {
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
        FacesContext.getCurrentInstance().addMessage("successInfo", facesMsg);
    }

    /**
     * Obtiene una Reserva con el id correspondiente.
     * @param id
     * @return Reserva
     */
    public Reserva findReserva(Integer id) {
        EntityManager em = getEntityManager();
        try {
            Reserva o = (Reserva) em.find(Reserva.class, id);
            return o;
        } finally {
            em.close();
        }
    }
    
    /*
     * ------------------------------------------------------------------------
     * Funciones de Iteración
     * ------------------------------------------------------------------------
     */
    public int getItemCount() {
        if (itemCount == -1) {
            EntityManager em = getEntityManager();
            try {
                itemCount = ((Long) em.createQuery("select count(o) from Reserva as o where o.idestadoreserva=1").getSingleResult()).intValue();
            } finally {
                em.close();
            }
        }
        return itemCount;
    }

    public int getItemMax() {
        if (itemCount == -1) {
            EntityManager em = getEntityManager();
            try {
                itemCount = ((Long) em.createQuery("select count(o) from Reserva as o").getSingleResult()).intValue();
                if (itemCount > 0) {
                    Reserva d = (Reserva) em.createQuery("SELECT s FROM Reserva as s order by s.idReserva DESC").getResultList().get(0);
                    itemCount = d.getIdReserva();
                }
            } finally {
                em.close();
            }
        }
        return itemCount + 1;
    }

/*    public int getFirstItem() {
        getItemCount();
        if (firstItem >= itemCount) {
            if (itemCount == 0) {
                firstItem = 0;
            } else {
                int zeroBasedItemCount = itemCount - 1;
                double pageDouble = zeroBasedItemCount / batchSize;
                int page = (int) Math.floor(pageDouble);
                firstItem = page * batchSize;
            }
        }
        return firstItem;
    }

    public int getLastItem() {
        getFirstItem();
        return firstItem + batchSize > itemCount ? itemCount : firstItem + batchSize;
    }

    public int getBatchSize() {
        return batchSize;
    }

    public String next() {
        reset(false);
        getFirstItem();
        if (firstItem + batchSize < itemCount) {
            firstItem += batchSize;
        }
        return "reserva_list";
    }

    public String prev() {
        reset(false);
        getFirstItem();
        firstItem -= batchSize;
        if (firstItem < 0) {
            firstItem = 0;
        }
        return "reserva_list";
    }*/

    private String relatedControllerOutcome() {
        String relatedControllerString = getRequestParameter("jsfcrud.relatedController");
        String relatedControllerTypeString = getRequestParameter("jsfcrud.relatedControllerType");
        if (relatedControllerString != null && relatedControllerTypeString != null) {
            FacesContext context = FacesContext.getCurrentInstance();
            Object relatedController = context.getApplication().getELResolver().getValue(context.getELContext(), null, relatedControllerString);
            try {
                Class<?> relatedControllerType = Class.forName(relatedControllerTypeString);
                Method detailSetupMethod = relatedControllerType.getMethod("detailSetup");
                return (String) detailSetupMethod.invoke(relatedController);
            } catch (ClassNotFoundException e) {
                throw new FacesException(e);
            } catch (NoSuchMethodException e) {
                throw new FacesException(e);
            } catch (IllegalAccessException e) {
                throw new FacesException(e);
            } catch (InvocationTargetException e) {
                throw new FacesException(e);
            }
        }
        return null;
    }

    /**
     * Borra la referencia al objeto Representado (Borrado sin persistencia).
     * @param resetFirstItem
     */
    public void reset(boolean resetFirstItem) {
        reserva = null;
        reservas = null;
        itemCount = -1;
    }
   
    private Map<Object, String> asString = null;

    /**
     * Función para Transformar la Reserva representada a una forma que pueda
     * ser transmitida en los jsps.
     * @return Map<Object, String>
     */
    public Map<Object, String> getAsString() {
        if (asString == null) {
            asString = new HashMap<Object, String>() {

                @Override
                public String get(Object key) {
                    if (key instanceof Object[]) {
                        Object[] keyAsArray = (Object[]) key;
                        if (keyAsArray.length == 0) {
                            return "(No Items)";
                        }
                        StringBuffer sb = new StringBuffer();
                        for (int i = 0; i < keyAsArray.length; i++) {
                            if (i > 0) {
                                sb.append("<br />");
                            }
                            sb.append(keyAsArray[i]);
                        }
                        return sb.toString();
                    }
                    return new ReservaConverter().getAsString(FacesContext.getCurrentInstance(), null, (Reserva) key);
                }
            };
        }
        return asString;
    }

    /**
     * Función que Vincula y Valida JSP con la Reserva Representada.
     * @param facesContext
     * @param component
     * @param value
     */
    public void validateCreate(FacesContext facesContext, UIComponent component, Object value) {
        ReservaConverter converter = new ReservaConverter();
        String newReservaString = converter.getAsString(FacesContext.getCurrentInstance(), null, new Reserva());
        String reservaString = converter.getAsString(FacesContext.getCurrentInstance(), null, reserva);
        if (!newReservaString.equals(reservaString)) {
            createSetup();
        }
    }
    
    /*
     * Función para controlar el solapamiento 
     * @return String
     */
    private String verificarSolapamiento(){
        EntityManager em = getEntityManager();
        Recurso RECURSOSELECCIONADO = new Recurso(this.reserva.getIdRecurso().getIdRecurso());
            String SQL;
        String finicio, ffin,hinicio,hfin;
        finicio=dateFormat.format(reserva.getFechaInicio());
        hinicio=horaFormat.format(reserva.getHoraInicio());
        ffin=dateFormat.format(reserva.getFechaFin());
        hfin=horaFormat.format(reserva.getHoraFin());
        try {
            SQL= "select f_verificar_solapamientohorario('"+finicio+"','"+hinicio+"','"+ffin+"','"+hfin+"','"+RECURSOSELECCIONADO.getIdRecurso()+"')";
            Query q = em.createNativeQuery(SQL);
            Vector v = new Vector();
            v  = (Vector) q.getSingleResult();
            String s = (String)v.get(0);
            return s;
        } 
        finally {
            em.close();
        }    
    }
}
